/* describes the game */
class WorldGame extends World {

	assets() {
		return [
			"images/crystal.png",
			"images/darek_run_0.png",
			"images/darek_run_1.png",
			"images/darek_run_2.png",
			"images/darek_run_3.png",
			"images/darek_run_4.png",
			"images/darek_run_5.png",
			"images/darek_run_6.png",
			"images/darek_run_7.png",
			"images/darek_stand.png",
			"images/game_bg.png",
			"images/button_shop.png",
			"images/button_spawn_speed.png",
			"images/button_spawn_value.png",
			"images/button_collector_quantity.png",
			"images/button_collector_speed.png",
			"images/button_spawn_limit.png",
			"images/button_options.png",
			"images/button_quit.png",
		];
	}

	/* initialize game */
	start() {

		/* interface data */
		let PADDING = 10;

		/* game data */
		this.shop = new Shop();
		this.pickups = 0;
		this.paused = false;

		/* background, tile image */
		let bg = new PIXI.extras.TilingSprite(
			loader.resources["images/game_bg.png"].texture,
			width, height
			);
		app.stage.addChild(bg);

		/* container of everything that "stands" on the ground
		 * everything in this container should be sorted based on the
		 * bottom side of its sprite, to emulate objects that are behind
		 * other objects
		 */
		this.ground_container = new PIXI.Container();
		app.stage.addChild(this.ground_container);

		/* spawner of crystals */
		this.spawner = new PickupSpawner(this.ground_container,
			this.shop.get_data(this.shop.SPAWN_SPEED),
			this.shop.get_data(this.shop.SPAWN_LIMIT));

		/* collectors */
		this.collector_array = [];
		Collector.new_timer = this.shop.get_data(this.shop.COLLECTOR_SPEED);

		/* text to display pickups */
		this.style = new PIXI.TextStyle(
			{
				fill: 0x6699ff,
				dropShadow: true,
				dropShadowColor: 0x000000,
				dropShadowBlur: 2,
				dropShadowDistance: 2,
			});
		this.text = new PIXI.Text("hello world", this.style);
		this.text.x = PADDING;
		this.text.y = PADDING;
		app.stage.addChild(this.text);

		/* open-close shop button and its animation 
		 * used to animate shop buttons
		 */
		this.button_open_shop = new PIXI.Sprite( loader.resources["images/button_shop.png"].texture );
		this.button_open_shop.position.set( PADDING, height -this.button_open_shop.height -PADDING );
		app.stage.addChild(this.button_open_shop);
		this.anim_open_shop = new Animation(15);

		/* shop buttons */
		this.shop_buttons = [
			new PIXI.Sprite( loader.resources["images/button_spawn_speed.png"].texture ),
			new PIXI.Sprite( loader.resources["images/button_spawn_value.png"].texture ),
			new PIXI.Sprite( loader.resources["images/button_collector_quantity.png"].texture ),
			new PIXI.Sprite( loader.resources["images/button_collector_speed.png"].texture ),
			new PIXI.Sprite( loader.resources["images/button_spawn_limit.png"].texture )
		];

		/* text for shop prices */
		this.txt_shop = [
			new PIXI.Text("", this.style),
			new PIXI.Text("", this.style),
			new PIXI.Text("", this.style),
			new PIXI.Text("", this.style),
			new PIXI.Text("", this.style),
		];
		this.update_text();

		/* place buttons horizontally, equal distance from each other 
		 * and below the screen (they show when they are animated)
		 */
		for (let i = 0; i < this.shop_buttons.length; i++) {
			this.shop_buttons[i].x = width /(this.shop_buttons.length+1) *(i+1)
				-this.shop_buttons[i].width/2;
			this.shop_buttons[i].y = height;
			app.stage.addChild(this.shop_buttons[i]);

			/* texts */
			this.txt_shop[i].anchor = {x:0.5, y:1};
			this.txt_shop[i].position.set( this.shop_buttons[i].x +this.shop_buttons[i].width/2,
				this.shop_buttons[i].y -this.shop_buttons[i].height);
			this.txt_shop[i].visible = false;
			app.stage.addChild(this.txt_shop[i]);
		}

		/* options button */
		this.button_options = new PIXI.Sprite(
			loader.resources["images/button_options.png"].texture
		);
		this.button_options.x = width -this.button_options.width -PADDING;
		this.button_options.y = PADDING;
		app.stage.addChild(this.button_options);

		/* quit button */
		this.button_quit = new PIXI.Sprite(
			loader.resources["images/button_quit.png"].texture
		);
		this.button_quit.x = width;
		this.button_quit.y = this.button_options.y +this.button_options.height
			+PADDING;
		app.stage.addChild(this.button_quit);

		/* quit button animation */
		this.anim_quit = new Animation(15);

		/* paused text */
		this.txt_paused = new PIXI.Text("Paused", this.style);
		this.txt_paused.anchor = {x:0.5, y:0.5};
		this.txt_paused.position.set(width/2, height/2);
		this.txt_paused.visible = false;
		app.stage.addChild(this.txt_paused);

		/* button sound */
		this.button_sound = new Audio("audio/button_click.mp3");

		/* theme music */
		this.theme = new Audio("audio/collector_game.mp3");
		this.theme.addEventListener('ended', function() {
                        this.currentTime = 0;
                        this.play();
                }, false);
		if (!muted) {
	                this.theme.play();
		}

		/* fade in animation */
		this.fade_in = new PIXI.Graphics();
		this.fade_in.beginFill(0x000000);
		this.fade_in.drawRect(0, 0, width, height);
		this.fade_in.endFill();
		this.fade_in.alpha = 1;
		app.stage.addChild(this.fade_in);
		this.anim_open = new Animation(15);
		this.anim_open.start();

	} /* start */

	/* runs once each frame */
	update() {

		/* opening animation */
		if (this.anim_open.update()) {

			/* when animation ends, remove rectangle */
			if (!this.anim_open.is_running()) {
				this.fade_in.visible = false;

				/* animation is back in the beginning
				 * a new world is opening
				 */
				if (this.anim_open.timer == 0) {
					this.theme.pause();
					return 0;
				}
			}

			/* animate rectangle alpha to fade in */
			this.fade_in.alpha = 1 -this.anim_open.interpolate(1);
			this.theme.volume = this.anim_open.interpolate(1);

			/* ignore input and update during animation */
			return;

		} /* opening animation */

		/* handle input */
		for (let e = 0; e < input.length; e++) {

			/* mouse left click */
			if (input[e].which == 1) {

				/* save clicking point */
				let p = new PIXI.Point(input[e].offsetX, input[e].offsetY);

				/* clicked on options button */
				if (this.button_options.containsPoint(p)) {
					if (!muted) this.button_sound.play();
					this.paused = !this.paused;
					this.txt_paused.visible = this.paused;
					this.anim_quit.flip();
				}

				/* clicked on quit button */
				if (this.button_quit.containsPoint(p)) {
					if (!muted) this.button_sound.play();
					this.anim_open.start();
					this.fade_in.visible = true;
				}

				/* clicked on open-close shop button */
				if (this.button_open_shop.containsPoint(p)) {

					/* play sound */
					if (!muted) this.button_sound.play();

					/* animate buttons */
					this.anim_open_shop.flip();

					/* make prices invisible */
					for (let i = 0; i < this.txt_shop.length; i++) {
						this.txt_shop[i].visible = false;
					}

					/* touch only one button per input */
					break;

				} /* button open-close shop */

				/* clicked on a crystal, only if game is not paused */
				if (!this.paused) {
					let i;
					if ((i = this.spawner.collect(p)) > -1) {
						this.pickup(i);
					}
				} /* clicked on pickup */

				/* clicked on shop button */
				for (let i = 0; i < this.shop_buttons.length; i++) {

					/* find which button it was */
					if (this.shop_buttons[i].containsPoint(p)) {

						/* user attempted to buy something */
						this.buy_something(i);

						/* one touch per input */
						break;

					} /* which shop button */

				} /* shop buttons */

			} /* left click */

		} /* handle input */

		/* quit button is animating */
		if (this.anim_quit.update()) {
			this.button_quit.x = width -this.anim_quit.interpolate(
				this.button_quit.width +10);
		}

		/* game is paused, do not update anything
		 * except animation for quit button
		 */
		if (this.paused) {
			return;
		}

		/* shop buttons animation */
		if (this.anim_open_shop.update()) {

			/* make all buttons move from below the screen
			 * to the bottom part of the screen
			 */
			for (let i = 0; i < this.shop_buttons.length; i++) {
				this.shop_buttons[i].y =
					height -this.anim_open_shop.interpolate(this.shop_buttons[0].height +10);
			}

			/* animation stopped */
			if (!this.anim_open_shop.is_running()) {

				if (this.anim_open_shop.timer == this.anim_open_shop.max) {
					for (let i = 0; i < this.txt_shop.length; i++) {
						this.txt_shop[i].visible = true;
					}
				}
			}

		} /* shop buttons animation */

		/* update spawner (to make more pickups) */
		this.spawner.update();

		/* update collectors */
		for (let i = 0; i < this.collector_array.length; i++) {
			this.collector_array[i].update();
		}

	} /* update */

	/* show how many pickups have been picked up on the screen
	 * and shop prices
	 */
	update_text() {
		this.text.text = "pickups: " +this.pickups;
		for (let i = 0; i < this.txt_shop.length; i++) {
			this.txt_shop[i].text = this.shop.cost(i);
		}
	}

	/* user attempted to buy something,
	 * handle everything here (TO DO)
	 */
	buy_something(i) {

		/* play sound */
		if (!muted) {
			this.button_sound.play();
		}

		/* user has enough crystals */
		let cost = this.shop.cost(i);
		if (this.pickups >= cost) {

			/* pay price */
			this.pickups -= cost;

			/* buy shop level */
			let data = this.shop.increase_data(i);
			this.update_text();

			if ( this.shop.get_counter(i) == 8 ) {
				this.shop_buttons[i].visible = false;
			}

			/* change game data depending on what changed */
			switch (i) {
				case 0:
					this.spawner.set_speed(this.shop.get_data(this.shop.SPAWN_SPEED));
					console.log("new spawn speed: " +this.spawner.anim_spawn.max);
					break;
				case 1:
					console.log("new spawn value: " +this.shop.get_data(this.shop.SPAWN_VALUE));
					break;
				case 2:
					for (let i = 0; i < data; i++) {
						this.collector_array.push( new Collector(this) );
					}
					console.log("total number of collectors: " +this.collector_array.length);
					break;
				case 3:
					Collector.new_timer = this.shop.get_data(
						this.shop.COLLECTOR_SPEED);
					console.log("collector speed: ", Collector.new_timer);
					break;
				case 4:
					this.spawner.limit = this.shop.get_data(this.shop.SPAWN_LIMIT);
					console.log("pickup limit: " +this.spawner.limit);
					break;
			} /* switch data type */

		} /* user can pay cost */

	} /* buy something */

	/* picked up crystal with index i */
	pickup(i) {

		/* show current pickups on screen */
		this.pickups += this.shop.get_data(this.shop.SPAWN_VALUE);
		this.update_text();

		/* remove crystal from ground container and spawner */
		this.ground_container.removeChild(this.spawner.array[i]);
		this.spawner.array.splice(i, 1);

		/* notify all collectors that crystal was picked up */
		for (let j = 0; j < this.collector_array.length; j++) {
			this.collector_array[j].notify_collected(i);
		}

	} /* pickup */

} /* game world */
